package com.gcloud.mesh.asset.utils.supervisionsystem;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gcloud.mesh.asset.dao.IaasDao;
import com.gcloud.mesh.asset.dao.NodeDao;
import com.gcloud.mesh.asset.dao.SwitcherDao;
import com.gcloud.mesh.asset.entity.IaasEntity;
import com.gcloud.mesh.asset.enums.DeviceType;
import com.gcloud.mesh.asset.enums.XbrotherDefaultDeviceType;
import com.gcloud.mesh.asset.enums.XbrotherDeviceType;
import com.gcloud.mesh.header.enums.ResourceSourceType;
import com.gcloud.mesh.header.vo.asset.DeviceItemVo;
import com.gcloud.mesh.header.vo.supplier.XbortherAssetItemVo;
import com.gcloud.mesh.header.vo.supplier.XbrotherSupervisionSystemVo;
import com.gcloud.mesh.supplier.dao.SupplierDao;
import com.gcloud.mesh.supplier.entity.SupplierEntity;
import com.gcloud.mesh.utils.SupplierSystemTypeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Component
@ConditionalOnProperty(name = "asset.supervision_system", havingValue = "xbrother")
public class XbrotherSupervisionSystem implements ISupervisionSystem {
	
	private static final String HTTP = "http://";
	
	private RestTemplate restTemplate = new RestTemplate();
	
	private static final String GENERAL = "general";
	
	private static final String TYPE = "supervision_system_xbrother";
	
	@Autowired
	private IaasDao iaasDao;

	@Autowired
	private NodeDao nodeDao;

	@Autowired
	private SwitcherDao switcherDao;
	
	@Autowired
    private SupplierDao supplierDao;

	@Override
	public <E> List<E> sync(Class clazz) {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	public void syncDevice(int type) {
		// TODO Auto-generated method stub
		List<SupplierEntity> suppliers = supplierDao.findAll().stream().filter( s -> TYPE.equals(s.getType())).collect(Collectors.toList());
		for(SupplierEntity supplier: suppliers) {
			XbrotherSupervisionSystemVo obj = (XbrotherSupervisionSystemVo)SupplierSystemTypeUtil.getByName(supplier.getType(), supplier.getConfig());
			List<XbortherAssetItemVo> items = listAssets(obj.getHostIp(), obj.getLoginCode());
			Map<String, Object> props = new HashMap<String, Object>();
			props.put("datacenter_id", supplier.getDatacenterId());
			props.put("from", ResourceSourceType.SYNC.getName());
//			List<Integer> types = Arrays.asList(1, 2, 8);
//			List<DeviceItemVo> devices = iaasDao.findByProperties(props, DeviceItemVo.class).stream().filter( s -> types.contains(s.getType())).collect(Collectors.toList());
			List<DeviceItemVo> devices = iaasDao.findByProperties(props, DeviceItemVo.class).stream().filter( s -> s.getType() == type).collect(Collectors.toList());
			saveDevice(items, devices, supplier.getDatacenterId());
			updateDevice(items, devices, supplier.getDatacenterId());
			deleteDevice(items, devices);
		}
	}
	
	@Override
	public void syncNodeAndSwitcher(int type) {
		// TODO Auto-generated method stub
		List<SupplierEntity> suppliers = supplierDao.findAll().stream().filter( s -> TYPE.equals(s.getType())).collect(Collectors.toList());
		for(SupplierEntity supplier: suppliers) {
			XbrotherSupervisionSystemVo obj = (XbrotherSupervisionSystemVo)SupplierSystemTypeUtil.getByName(supplier.getType(), supplier.getConfig());
			List<XbortherAssetItemVo> items = listAssets(obj.getHostIp(), obj.getLoginCode());
			Map<String, Object> props = new HashMap<String, Object>();
			props.put("datacenter_id", supplier.getDatacenterId());
			props.put("from", ResourceSourceType.SYNC.getName());
//			List<Integer> types = Arrays.asList(3, 4);
//			List<DeviceItemVo> devices = iaasDao.findByProperties(props, DeviceItemVo.class).stream().filter( s -> types.contains(s.getType())).collect(Collectors.toList());
			List<DeviceItemVo> devices = iaasDao.findByProperties(props, DeviceItemVo.class).stream().filter( s -> s.getType() == type).collect(Collectors.toList());
			saveItDevice(items, devices, supplier.getDatacenterId());
			updateItDevice(items, devices, supplier.getDatacenterId());
			deleteItDevice(items, devices);
		}
	}
	
	private String getSession(String hostIp, String loginCode) {

		String uri = "http://" + hostIp + "/api/v3/auth/sso/login";
		JSONObject postData = new JSONObject();
		postData.put("text", loginCode);
		String session = null;
		try {
			JSONObject json = restTemplate.postForEntity(uri, postData, JSONObject.class).getBody();
			JSONObject data = json.getJSONObject("data");
			session = data.getString("session");
		} catch(Exception e) {
			log.error("supplier system {} login error: {}", hostIp, e.getMessage());
		}
		return session;
	}
	
	public List<XbortherAssetItemVo> listAssets(String hostIp, String loginCode) {
		String token = getSession(hostIp, loginCode);
		String unixTimeStamp = Long.toString(System.currentTimeMillis());
		String uri = HTTP + hostIp +  "/api/v2/mblock/asset/list?order=DESC&_=" + unixTimeStamp;
		HttpHeaders headers = new HttpHeaders();
		headers.set("cookie", "X_GU_SID=" + token);
		HttpEntity<JSONObject> httpEntity = new HttpEntity<JSONObject>(headers);
		
		List<XbortherAssetItemVo> assets = new ArrayList<XbortherAssetItemVo>();
		try {
			JSONObject json = restTemplate.getForObject(uri, JSONObject.class, httpEntity);
			JSONArray jsonArray = json.getJSONArray("rows");
			if(jsonArray.size() > 0) {
				for(int i=0; i<jsonArray.size(); i++) {
					JSONObject obj = jsonArray.getJSONObject(i);
					XbortherAssetItemVo vo = (XbortherAssetItemVo)JSONObject.parseObject(obj.toString(), XbortherAssetItemVo.class);
					assets.add(vo);
				}
			}
		} catch(Exception e) {
			log.error("supplier system {} list error: {}", hostIp, e.getMessage());
		}
		return assets;
	}
	
	private void saveDevice(List<XbortherAssetItemVo> items, List<DeviceItemVo> devices, String datacenterId) {
		
		List<String> exists = devices.stream().map( s -> s.getName()).collect(Collectors.toList());
		List<XbortherAssetItemVo> newItems = items.stream().filter( s -> !exists.contains(s.getName())).collect(Collectors.toList());
		if(newItems != null) {
			for(XbortherAssetItemVo vo: newItems) {
				IaasEntity iaas = new IaasEntity();
				iaas.setId(UUID.randomUUID().toString());
				iaas.setName(vo.getName());
				iaas.setEsn(GENERAL);
				iaas.setDatacenterId(datacenterId);
				iaas.setCreator(null);
				iaas.setCreateTime(new Date());
				iaas.setDeviceManufacturer(GENERAL);
				iaas.setDeviceModel(GENERAL);
//				iaas.setVisible(true);
				iaas.setFrom(ResourceSourceType.SYNC.getName());

				if(XbrotherDefaultDeviceType.getDeviceTypeByCnName(vo.getName()) != null) {
					iaas.setType(XbrotherDefaultDeviceType.getDeviceTypeByCnName(vo.getName()).getDeviceType().getNo());
				} else {
					if(XbrotherDeviceType.getDeviceTypeByCnName(vo.getDevice_info()) != null) {
						iaas.setType(XbrotherDeviceType.getDeviceTypeByCnName(vo.getDevice_info()).getDeviceType().getNo());
					} else {
						iaas.setType(DeviceType.GENERAL.getNo());
					}
				}

				try {
					iaasDao.save(iaas);
				} catch(Exception e) {
					log.error("save deivce resource from supervision system failed : {}", e.getMessage());
				}
			}
		}		
	}
	
	private void updateDevice(List<XbortherAssetItemVo> items, List<DeviceItemVo> devices, String datacenterId) {
		
	}
	
	private void deleteDevice(List<XbortherAssetItemVo> items, List<DeviceItemVo> devices) {
		List<String> exists = items.stream().map( s -> s.getName()).collect(Collectors.toList());
		List<DeviceItemVo> deletes = devices.stream().filter( s -> !exists.contains(s.getName())).collect(Collectors.toList());
		if(deletes != null) {
			for(DeviceItemVo vo: deletes) {
				try {
					iaasDao.deleteById(vo.getId());
				} catch(Exception e) {
					log.error("delete deivce resource from supervision system failed : {}", e.getMessage());
				}
			}
		}
	}	
	
	private void saveItDevice(List<XbortherAssetItemVo> items, List<DeviceItemVo> devices, String datacenterId) {
			
	}
	
	private void updateItDevice(List<XbortherAssetItemVo> items, List<DeviceItemVo> devices, String datacenterId) {
		
	}
	
	private void deleteItDevice(List<XbortherAssetItemVo> items, List<DeviceItemVo> devices) {

	}	
	
}
